package java模板模式;

/**
 * @author coderFu
 * @create 2022/3/3
 *
 * 模板方法模式： 在一个方法中定义一个算法骨架
 * 而将一些步骤延迟到子类中，模板方法使得子类在不改变
 * 算法结构的情况下，重新定义算法中的某些步骤
 * 【钩子方法】： 原理就是实现为空的方法，在某些任务之前
 * 之后、执行中，报异常后调用的方法，
 */

abstract class ModelClient {

    /**
     * 模板方法
     */
    public void templateMethod(){
        before();
        appetite();
        after();
    }


    /**
     * 钩子方法  在盛饭前（一个空的实现）
     */
    protected void before(){

    };

    /**
     *
     *    // 模板模式理解
     *     // 抽象方法和空实现方法的区别，当要实例化对象调用的时候
     *     抽象方法必须实现，空方法可以不用实现
     *
     *   模板模式是父类提供模板方，子类提供具体实现，对于字类需要实现的方法
     *   父类写成抽象方法，强制子类实现，对于子类不需要实现的方法
     *   所有子类相同的方法，父类设计为空实现（灵活使用）
     *
     *   模板方法中具体方法到底是空时先还是抽象方法本身没有什么区别，
     *   只是为了设计优美，让子类只实现自己需要的抽象方法，仅仅设计
     *   优美而已
     *
     *   模板模式两要素：父类的模板方法（注意，模板方法一定要放在父类
     *   并完全实现，并对子类可见，protected 或者public）+子类实现具体
     *   方法
     *
     *
     *   模板模式可以不需要回调方法和钩子
     *   模板模式与回调方法关系可以有关也可以无关
     *   模板模式与钩子方法可以无关也可以有关
     *
     *
     *   回调方法：
     *   回调方法定义：通过传递来调用引用指定对象的方法，回调方法一定
     *   涉及两个类，通过方法参数接收另外一个类的引用来调用另外一个类
     *
     *   回调方法就是一个通过回调对象的引用（java中的引用存的是对象的地址）
     *   调用的方法，如果你把回调对象的引用（地址）作为参数传递给另外一个
     *   方法，当这个引用被用来调用其他所指向的方法时，我们就说这是回调方法。
     *
     *
     *   钩子方法：
     *   钩子方法的定义：通过一个方法来干涉另外一个方法的行为，就是一个方法的
     *   返回结果或修改的变量是另一个方法执行时的if判断条件或for/while循环调用
     *   条件。
     *
     *   一个类中一个方法的返回结果或修改的变量是另一个类中的方法提供的
     *  时候，参数和类变量就要提供类外一个类的引用了，静态方法则不必
     *
     *  当某个方法的判断条件需要子类提供或父类提供的话，就是用到了钩子了
     *  最常见的是，父类方法需要子类实现作为判断条件，就是子类控制父类行为
     *  这是模板方法中最常见的情况
     */

    /**
     * 抽象方法 ， 告诉服务员其饭量 必须实现的
     */
    public abstract void appetite();


    public void after(){
        //盛饭后  所有类都要做的
        System.out.println("拿筷子，找桌子，开吃");
    }
}

class Test1{

    // 业务处理类，老王去打饭

    public static void main(String[] args) {
        new ModelClient(){

            /**
             * 可以自由添加的 钩子 空实现
             */
            @Override
            protected void before() {
                System.out.println("对服务员吹胡子瞪眼");
            }

            @Override
            public void appetite() {
                System.out.println("盛了一锅米饭");
            }
        }.templateMethod();

    }





}
